home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / comm / misc / xqsrc1_7.lzh / library / file.c < prev    next >
C/C++ Source or Header  |  1993-03-12  |  11KB  |  516 lines

  1. /*
  2.  *    Name:                file.c
  3.  *
  4.  * Description:    File related functions for xferq.library
  5.  *
  6.  * Copyright:        1992-1993 by David Jones.
  7.  *
  8.  * Distribution:
  9.  *        This program is free software; you can redistribute it and/or modify
  10.  *        it under the terms of the GNU General Public License as published by
  11.  *        the Free Software Foundation; either version 2 of the License, or
  12.  *        (at your option) any later version.
  13.  *
  14.  *        This program is distributed in the hope that it will be useful,
  15.  *        but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *        GNU General Public License for more details.
  18.  *
  19.  *        You should have received a copy of the GNU General Public License
  20.  *        along with this program; if not, write to:
  21.  *
  22.  *                The Free Software Foundation        David Jones
  23.  *                675 Mass Ave                            6730 Tooney Drive
  24.  *                Cambridge, MA                            Orleans, Ontario
  25.  *                02139                                        K1C 6R4
  26.  *                USA                                        Canada
  27.  *
  28.  *    Usenet:    gnu@prep.ai.mit.edu                    aa457@freenet.carleton.ca
  29.  *    Fidonet:                                                1:163/109.8
  30.  *
  31.  *        $Log: $
  32.  *
  33.  */
  34.  
  35. #include <exec/types.h>
  36. #include <execlists.h>
  37. #include <dos/dos.h>
  38. #include <dos/dosasl.h>
  39. #include <proto/dos.h>
  40. #include <proto/exec.h>
  41. #include <string.h>
  42. #include "xferq.h"
  43. #include "xferqint.h"
  44. #include "xferq_pragmas.h"
  45.  
  46. extern BOOL QueueScanned;
  47. extern struct NetAddress *DefaultAddr;
  48.  
  49. char *FidoName = "_$(DOMAIN:S).$(ZONE:D).$(NET:D).$(NODE:D).$(POINT:D).queue";
  50. char *UucpName = "_UUCP.$(UUCPNAME:S).queue";
  51. char *TextName = "_TEXT.$(TEXTNAME:S).queue";
  52. BOOL ConfigRead;
  53.  
  54. char *MakeFileName(struct NetAddress *addr)
  55. /*
  56.  *    In:    addr                Address to make filename for
  57.  *
  58.  *    Does:    Constructs the filename for a queue file given the address.
  59.  *
  60.  */
  61. {
  62. struct VarList *vl;
  63. char *template, *filename;
  64. #ifdef DEBUG
  65.     int count = GetCount(addr);
  66. #endif
  67.  
  68.     switch (addr->type) {
  69.     case XQNT_FIDO:
  70.         template = FidoName;
  71.         break;
  72.     case XQNT_UUCP:
  73.         template = UucpName;
  74.         break;
  75.     case XQNT_TEXT:
  76.         template = TextName;
  77.         break;
  78.     default:
  79.         return NULL;
  80.     }
  81.     vl = NewVarList();
  82.     if (!vl) {
  83.         return NULL;
  84.     }
  85.     if (ExamObjectVarList(addr, vl)) {
  86.         filename = MakeString(NULL, template, vl);
  87.     }
  88.     else {
  89.         filename = NULL;
  90.     }
  91.     DropVarList(vl);
  92. #ifdef DEBUG
  93.     CheckCount("MakeFileName", addr, count);
  94. #endif
  95.     return filename;
  96. }
  97.  
  98.  
  99. ULONG __saveds __asm LIBNextSeq(void)
  100. /*
  101.  *    Does:    Returns a unique 32-bit sequence number each time the function
  102.  *            is called.  The numbers will repeat after 2^32 calls.
  103.  */
  104. {
  105.  
  106.     return 0;
  107. }
  108.  
  109.  
  110. ULONG TruncateFile(char *name)
  111. /*
  112.  *    In:    name                Name of file to truncate
  113.  *
  114.  * Does:    The file is given zero length, although it still exists.
  115.  *            The function returns the appropriate XfqRemoveWork() code.
  116.  */
  117. {
  118. BPTR fh;
  119.  
  120.     fh = Open(name, MODE_OLDFILE);
  121.     if (fh) {
  122.         SetFileSize(fh, OFFSET_BEGINNING, 0);
  123.         Close(fh);
  124.         return XQRM_TRUNCATED;
  125.     }
  126.     else {
  127.         Error(XQERROR_DOS);
  128.         return XQRM_ERROR;
  129.     }
  130. }
  131.  
  132.  
  133. char *FullPath(char *name)
  134. /*
  135.  *    In:    name                Name to take full path of
  136.  *
  137.  * Does:    Returns a string object which is the fully-qualified path name
  138.  *            of the input.
  139.  */
  140. {
  141. char buf[258];
  142. int i, len;
  143. BPTR lock;
  144. BOOL rc;
  145.  
  146.     len = strlen(name);
  147.     for (i = 0; i < len; i++) {
  148.         if (name[i] == ':') {
  149.             return CopyString(name);
  150.         }
  151.     }
  152.     lock = Lock(name, ACCESS_READ);
  153.     if (lock) {
  154.         rc = NameFromLock(lock, buf, sizeof(buf));
  155.         UnLock(lock);
  156.         if (rc) {
  157.             return CopyString(buf);
  158.         }
  159.         else {
  160.             Error(XQERROR_DOS);
  161.             return NULL;
  162.         }
  163.     }
  164.     Error(XQERROR_DOS);
  165.     return NULL;
  166. }
  167.  
  168.  
  169. BOOL ReadQueueContents(BPTR file, struct SiteNode *sn)
  170. /*
  171. *    In:    file            File containing contents of queue.
  172. *            sn                Site node to read into.
  173. *
  174. *    Does:    Reads the contents of the file, forming the entries for the
  175. *            site queue.  The function returns TRUE on success, FALSE
  176. *            otherwise.
  177. */
  178. {
  179. char line[260];
  180. struct WorkNode *wn;
  181. long n, len;
  182. char *cp;
  183.  
  184.     while (FGets(file, line, sizeof(line))) {
  185.         wn = XfqCreateObject(XQO_WORKNODE, NULL);
  186.         if (!wn) {
  187.             DropSiteNode(sn);
  188.             return FALSE;
  189.         }
  190.         while (line[0] != '#') {
  191.             switch (line[0]) {
  192.             case 'F':
  193.                 len = strlen(line) - 2;    /* Drop header and newline */
  194.                 wn->node.ln_Name = CopyStringN(&line[1], len);
  195.                 if (!wn->node.ln_Name) {
  196. #ifdef DEBUG
  197.     kprintf("No mem for name\n");
  198. #endif
  199.                     XfqDropObject(wn);
  200.                     DropSiteNode(sn);
  201.                     return FALSE;
  202.                 }
  203.                 break;
  204.             case 'A':
  205.                 len = strlen(line) - 2;    /* Drop header and newline */
  206.                 wn->asname = CopyStringN(&line[1], len);
  207.                 if (!wn->asname) {
  208. #ifdef DEBUG
  209.     kprintf("No mem for asname\n");
  210. #endif
  211.                     XfqDropObject(wn);
  212.                     DropSiteNode(sn);
  213.                     return FALSE;
  214.                 }
  215.                 break;
  216.             case 'P':
  217.                 cp = &line[1];
  218.                 GetNumber(cp, 10, 0, &n);
  219.                 wn->node.ln_Pri = n;
  220.                 break;
  221.             case 'C':
  222.                 cp = &line[1];
  223.                 GetNumber(cp, 10, 0, &n);
  224.                 wn->userFlags = n;
  225.                 break;
  226.             case 'S':
  227.                 cp = &line[1];
  228.                 GetNumber(cp, 10, 0, &n);
  229.                 wn->status = n;
  230.                 break;
  231.             }
  232.             if (!FGets(file, line, sizeof(line)) && IoErr()) {
  233. #ifdef DEBUG
  234.     kprintf("Tail fail %d\n", IoErr());
  235. #endif
  236.                 Error(XQERROR_DOS);
  237.                 DropSiteNode(sn);
  238.                 return FALSE;
  239.             }
  240.         } /* while != '#' */
  241.         /*
  242.          *    Can't use AddWork() cuz that will recurse!
  243.          */
  244.         XfqCopyObject(sn->site);
  245.         wn->site = sn;
  246.         wn->addr = sn->site;
  247.         wn->sysFlags = XQ_INQUEUE;
  248.         ADDHEAD(&sn->workList, wn);
  249.     } /* while not EOF or error*/
  250.     if (IoErr()) {
  251. #ifdef DEBUG
  252.     kprintf("Done fail %d\n", IoErr());
  253. #endif
  254.         Error(XQERROR_DOS);
  255.         DropSiteNode(sn);
  256.         return FALSE;
  257.     }
  258.     sn->flags &= ~XQSITE_UNREAD;
  259. #ifdef DEBUG
  260.     kprintf("Read in OK\n");
  261. #endif
  262.     return TRUE;
  263. }
  264.  
  265.  
  266. void ReadQueue(struct SiteNode *sn)
  267. /*
  268.  *    In:    sn                    Site node to read queue for
  269.  *
  270.  * Does:    Reads the queue file from disk.
  271.  *
  272.  */
  273. {
  274. char *name;
  275. BPTR cdLock, oldLock;
  276. BPTR file;
  277. BOOL readOk;
  278. LONG ioErr;
  279.  
  280.     cdLock = Lock("XFERQ:", SHARED_LOCK);
  281.     if (!cdLock) {
  282.         Error(XQERROR_DOS);
  283.         return;
  284.     }
  285.     oldLock = CurrentDir(cdLock);
  286.     name = MakeFileName(sn->site);
  287. #ifdef DEBUG
  288.     kprintf("Reading %s\n", name);
  289. #endif
  290.     if (name) {
  291.         file = Open(&name[1], MODE_OLDFILE);
  292.         if (file) {
  293.             readOk = ReadQueueContents(file, sn);
  294.             ioErr = IoErr();
  295.             Close(file);
  296.             if (readOk) {
  297.                 /* Delete _file if file exists and was read in OK. */
  298.                 DeleteFile(name);
  299.             }
  300.             if (!ioErr) {
  301.                 /* Error was due to memory problem -> fail */
  302.                 goto endread;
  303.             }
  304.         }
  305.  
  306.         file = Open(name, MODE_OLDFILE);
  307.         if (file) {
  308.             ReadQueueContents(file, sn);
  309.             Close(file);
  310.             if (readOk) {
  311.                 /*
  312.                  *        New file was OK so move it over.
  313.                  *        If old file exists, but was corrupted, then this
  314.                  *        will fail.  Human intervention is probably
  315.                  *        required here.  For further study.
  316.                  */
  317.                 Rename(name, &name[1]);
  318.             }
  319.         }
  320.     }
  321. endread:
  322.     XfqDropObject(name);
  323.     CurrentDir(oldLock);
  324.     UnLock(cdLock);
  325. }
  326.  
  327.  
  328. BOOL WriteQueue(struct ExtSessWalk *esw)
  329. /*
  330.  *    In:    addr                Address to write queue for
  331.  *
  332.  * Does:    Writes the queue file to disk.
  333.  *
  334.  */
  335. {
  336. char *name;
  337. BPTR fh;
  338. BPTR cdLock, oldLock;
  339. struct WorkNode *wn;
  340. struct SiteNode *sn;
  341.  
  342.     sn = esw->sn;
  343.     if (!(sn->flags & XQSITE_DIRTY)) {
  344.         return TRUE;
  345.     }
  346.     cdLock = Lock("XFERQ:", SHARED_LOCK);
  347.     if (!cdLock) {
  348.         Error(XQERROR_DOS);
  349.         return FALSE;
  350.     }
  351.     name = MakeFileName(sn->site);
  352.     if (!name) {
  353.         return FALSE;
  354.     }
  355.     oldLock = CurrentDir(cdLock);
  356.     wn = FIRST(&sn->workList);
  357.     if (!NEXT(wn)) {
  358.         DeleteFile(&name[1]);
  359.         sn->flags &= ~XQSITE_DIRTY;
  360.     }
  361.     else {
  362.         fh = Open(name, MODE_NEWFILE);
  363.         if (fh) {
  364.             while (NEXT(wn)) {
  365.                 /*
  366.                  *        If IMMEDIATE is in effect, then anything that can cause
  367.                  *        the queue to be read in also nukes any sessions that
  368.                  *        were up so don't even bother to write these out.
  369.                  *
  370.                  *        Similar logic goes for SENDLATER, but this time we
  371.                  *        must clear the SENDLATER bit.
  372.                  */
  373.                 if (!(wn->userFlags & XQ_IMMEDIATE)) {
  374.                     FPrintf(fh, "F%s\n", wn->node.ln_Name);
  375.                     if (wn->asname) {
  376.                         FPrintf(fh, "A%s\n", wn->asname);
  377.                     }
  378.                     FPrintf(fh, "P%ld\n", wn->node.ln_Pri);
  379.                     FPrintf(fh, "C%ld\n", wn->userFlags & ~XQ_SENDLATER);
  380.                     FPrintf(fh, "S%ld\n", wn->status);
  381.                     FPrintf(fh, "#\n", NULL);
  382.                 }
  383.                 wn = NEXT(wn);
  384.             }
  385.             sn->flags &= ~XQSITE_DIRTY;
  386.             Close(fh);
  387.             DeleteFile(&name[1]);
  388.             Rename(name, &name[1]);
  389.         }
  390.         else {
  391.             Error(XQERROR_DOS);
  392.         }
  393.     }
  394.     CurrentDir(oldLock);
  395.     UnLock(cdLock);
  396.     return TRUE;
  397. }
  398.  
  399.  
  400. void ScanQueue(void)
  401. /*
  402.  *    Does:    Scans the queue directory for queue files.  For each queue file
  403.  *            found, it creates a site node and marks it as unread.
  404.  */
  405. {
  406. BPTR cdLock, oldLock;
  407. struct NetAddress *na;
  408. struct SiteNode *sn;
  409. struct AnchorPath *ap;
  410. struct VarList *vl;
  411. long error, type;
  412. char *name;
  413.  
  414.     cdLock = Lock("XFERQ:", SHARED_LOCK);
  415.     if (!cdLock) {
  416.         Error(XQERROR_DOS);
  417.         return;
  418.     }
  419.     oldLock = CurrentDir(cdLock);
  420.     ap = AllocObject(sizeof(struct AnchorPath), XQO_APATH);
  421.     vl = NewVarList();
  422.     if (ap && vl) {
  423.         ap->ap_Strlen = 0;
  424.         ap->ap_BreakBits = 0;
  425.         ap->ap_Flags = 0;
  426.         error = MatchFirst("#?.queue", ap);
  427.         while (!error) {
  428.             name = ap->ap_Info.fib_FileName;
  429.             if (name[0] == '_') {
  430.                 name++;    /* File is in error recovery mode. */
  431.             }
  432.             if (ScanString(name, &FidoName[1], vl)) {
  433.                 type = XQNT_FIDO;
  434.             }
  435.             else if (ScanString(name, &UucpName[1], vl)) {
  436.                 type = XQNT_UUCP;
  437.             }
  438.             else if (ScanString(name, &TextName[1], vl)) {
  439.                 type = XQNT_TEXT;
  440.             }
  441.             else {
  442.                 type = 0;    /* unknown type - ignore */
  443.             }
  444.             if (type) {
  445.                 na = XfqCreateObjectTags(XQO_ADDRESS,
  446.                     XQ_Network, type,
  447.                     TAG_DONE);
  448.                 if (na) {
  449.                     na = ModifyObjectVarList(na, vl);
  450.                 }
  451.                 EmptyVarList(vl);
  452.                 if (na) {
  453.                     sn = NewSiteQueue(na);
  454.                     XfqDropObject(na);
  455.                 }
  456.                 if (!na || !sn) {
  457.                     DropQueue();
  458.                     break;
  459.                 }
  460.                 else {
  461.                     sn->flags = XQSITE_UNREAD;
  462.                 }
  463.             }
  464.             error = MatchNext(ap);
  465.         }
  466.         switch (error) {
  467.         case ERROR_NO_MORE_ENTRIES:
  468.             QueueScanned = TRUE;
  469.             break;
  470.         case 0:
  471.             Error(XQERROR_NOMEM);
  472.             break;
  473.         default:
  474.             Error(XQERROR_DOS);
  475.             break;
  476.         }
  477.         MatchEnd(ap);
  478.     }
  479.     CurrentDir(oldLock);
  480.     if (ap) {
  481.         FreeObject(ap);
  482.     }
  483.     if (vl) {
  484.         DropVarList(vl);
  485.     }
  486.     UnLock(cdLock);
  487. }
  488.  
  489.  
  490. void ReadConfig(void)
  491. /*
  492.  *    Does:    Reads the configuration file.  At the moment, the file name
  493.  *            is XFERQ:hostaddr and contains the default domain and zone in
  494.  *            the form domain#zone.
  495.  */
  496. {
  497. BPTR fh;
  498. char line[40];
  499. struct NetAddress *na;
  500.  
  501.     na = NULL;
  502.     fh = Open("XFERQ:hostaddr", MODE_OLDFILE);
  503.     if (fh) {
  504.         if (FGets(fh, line, sizeof(line))) {
  505.             line[strlen(line) - 1] = '\0';
  506.             DefaultAddr = XfqGetAddressTags(line, NULL,
  507.                 XQ_Mandatory, XQADDR_2D,
  508.                 XQ_Optional, XQADDR_FIDO,
  509.                 TAG_DONE);
  510.         }
  511.         Close(fh);
  512.     }
  513.     ConfigRead = TRUE;
  514. }
  515.  
  516.